package com.ld.tamp.web.support;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ld.tamp.web.bean.ComponentAccessToken;
import com.ld.tamp.web.dao.ComponentAccessTokenDao;
import com.ld.tamp.web.dao.ComponentVerifyTicketDao;

import weixin.popular.api.ComponentAPI;

/**
 * 
 * 第三方平台token管理器
 * @author KeYang
 *
 */
public class ComponentTokenManager {

	private static final Logger logger = LoggerFactory.getLogger(ComponentTokenManager.class);

	private static ScheduledExecutorService scheduledExecutorService;

	private static Map<String, ScheduledFuture<?>> futureMap = new HashMap<String, ScheduledFuture<?>>();

	private static int poolSize = 2;

	private static boolean daemon = Boolean.TRUE;

	/**
	 * 初始化 scheduledExecutorService
	 */
	private static void initScheduledExecutorService() {
		logger.info("daemon:{},poolSize:{}", daemon, poolSize);
		scheduledExecutorService = Executors.newScheduledThreadPool(poolSize, new ThreadFactory() {
			@Override
			public Thread newThread(Runnable arg0) {
				Thread thread = Executors.defaultThreadFactory().newThread(arg0);
				// 设置守护线程
				thread.setDaemon(daemon);
				return thread;
			}
		});
	}

	/**
	 * 设置线程池
	 * 
	 * @param poolSize
	 *            poolSize
	 */
	public static void setPoolSize(int poolSize) {
		ComponentTokenManager.poolSize = poolSize;
	}

	/**
	 * 设置线程方式
	 * 
	 * @param daemon
	 *            daemon
	 */
	public static void setDaemon(boolean daemon) {
		ComponentTokenManager.daemon = daemon;
	}

	/**
	 * 初始化token 刷新，每118分钟刷新一次。
	 * @param componentVerifyTicketService 
	 * @param componentAccessTokenService 
	 * 
	 * @param appid
	 *            appid
	 * @param secret
	 *            secret
	 */
	public static void init(final String component_appid, final String component_appsecret, final int initialDelay, ComponentAccessTokenDao componentAccessTokenService, ComponentVerifyTicketDao componentVerifyTicketService) {

		if (scheduledExecutorService == null) {
			initScheduledExecutorService();
		}
		if (futureMap.containsKey(component_appid)) {
			futureMap.get(component_appid).cancel(true);
		}
		ScheduledFuture<?> scheduledFuture = scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
			@Override
			public void run() {
				try {
					 weixin.popular.bean.component.ComponentAccessToken componentAccessToken = ComponentAPI.api_component_token(component_appid,component_appsecret,componentVerifyTicketService.read());
					 if(componentAccessToken.isSuccess()){
						 ComponentAccessToken token = new ComponentAccessToken();
						 token.setComponentAccessToken(componentAccessToken.getComponent_access_token());
						 token.setExpiresTime(componentAccessToken.getExpires_in()*1000+System.currentTimeMillis());
						 componentAccessTokenService.save(token);
						 logger.info("COMPONENT ACCESS_TOKEN refurbish with appid:{}", component_appid);
					 }else{
						 throw new RuntimeException("COMPONENT ACCESS_TOKEN refurbish error");
					 }
				} catch (Exception e) {
					logger.error("COMPONENT ACCESS_TOKEN refurbish error with appid:{}", component_appid);
					//重新获取
					e.printStackTrace();
				}
			}
		}, initialDelay, 118, TimeUnit.MINUTES);
		futureMap.put(component_appid, scheduledFuture);
	}

	/**
	 * 取消 token 刷新
	 */
	public static void destroyed() {
		scheduledExecutorService.shutdownNow();
		logger.info("destroyed");
	}

	/**
	 * 取消刷新
	 * 
	 * @param appid
	 *            appid
	 */
	public static void destroyed(String appid) {
		if (futureMap.containsKey(appid)) {
			futureMap.get(appid).cancel(true);
			logger.info("destroyed appid:{}", appid);
		}
	}
}
